home *** CD-ROM | disk | FTP | other *** search
- /*
- * Batch.cmm
- *
- * Interpret a DOS batch file using CEnvi. This should work on all CEnvi
- * versions.
- */
-
- /* ---------------------------------------------------------------------- */
-
- usage()
- {
- printf("Use the BATCH command to interpret a DOS batch file under any system\n");
- printf("that CEnvi supports.\n");
- printf("Syntax:\n BATCH [filename] [args]\nwhere:\n");
- printf(" filename The .BAT file to be interpreted.\n");
- printf(" args Any number of arguments for the batch file.\n");
- exit(EXIT_FAILURE);;
- }
-
- /* ---------------------------------------------------------------------- */
-
- /*
- * Setup sets up all system dependent variables. Later, when #ifdef is working
- * this will be replaced using that.
- */
-
- search_path = ""; // make it global
- errorlevel = 0;
- echo = 1; // echo on
-
-
- setup()
- {
- if( defined(_NWNLM_) )
- {
- search_path = "SYS:/CENVI/";
- } else {
- if( defined(CMMPATH) ) search_path = CMMPATH;
- }
- }
-
- /*
- * Change the current directory to the given one. Return 0 if successful.
- */
- my_chdir(newdir)
- {
- if( defined(_NWNLM_) ) return chdir(newdir);
- if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
- {
- lReg.ah = 0x3B;
- if !defined(_DOS32_)
- lReg.ds = segment(newdir), lReg.dx = offset(newdir);
- else
- lReg.dx = pointer(newdir);
- interrupt(0x21,lReg,out);
-
- return out.ax;
- }
- if( defined(_NTCON_) || defined(_NTWIN_) )
- {
- return !DynamicLink("KERNEL32","SetCurrentDirectoryA",STDCALL,newdir);
- }
- if( defined(_OS2_) )
- {
- #define ORD_DOS32SETCURRENTDIR 255
- return DynamicLink("doscalls",ORD_DOS32SETCURRENTDIR,BIT32,CDECL,newdir);
- }
- }
-
- special_command = "__@%*&^%";
-
- /* ---------------------------------------------------------------------- */
-
- /*
- * The count is the number of params, the array is the params. These
- * correspond to %X where X is a digit. We also do %variable% for environment
- * variables, all uppercase.
- *
- * To ease processing, we kill the '\n' too.
- */
- substitute_line(line,count,array)
- {
- it = ""; i = 0; j = 0;
- while( line[i] )
- {
- if( line[i]!='%' )
- {
- if( line[i]!='\n' )
- {
- it[j++] = line[i];
- }
- i++;
- continue;
- }
- // Here we have a substitution...
- if( isdigit(line[i+1]) )
- {
- i += 2;
- num = line[i-1]-'0';
- if( num>=count ) continue; // no such argument
- for( k=0;array[num][k];k++ ) it[j++] = array[num][k];
- } else {
- if( line[++i]=='%' )
- {
- i++; it[j++] = '%'; continue;
- }
-
- env = ""; offset = 0;
- for( ;line[i] && !isspace(line[i]) && line[i]!='%';i++ )
- env[offset++] = line[i];
-
- if( isspace(line[i]) )
- {
- printf("Variable is not terminated.\n");
- return "";
- }
-
- env[offset] = 0; i++;
- value = "";
- sprintf(to_exec,"if( DataType(%s)==CMM_INT ) sprintf(value,\"%%d\",%s); else if( DataType(%s)==CMM_BYTE ) strcpy(value,%s);\n",env,env,env,env);
- Interpret(to_exec,INTERP_TEXT);
- while( value[0]!='\0' ) { it[j++] = value[0]; value++; }
- }
- }
- it[j] = '\0';
- return it;
- }
-
- /*
- * Search the appropriate places for the given name. If found, return the
- * full filename else return NULL.
- */
- find_cmm(name)
- {
- // First search the exact filename
- if( fp = fopen(name,"r") )
- {
- fclose(fp);
- return FullPath(name);
- }
-
- // Then search the filename converted to '.cmm'
- path = SplitFileName(name);
- sprintf(newname,"%s%s.cmm",path.dir,path.name);
- if( fp = fopen(newname,"r") )
- {
- fclose(fp);
- return FullPath(newname);
- }
-
- // Then search the converted filename using the search path.
- strcpy(tmppath,search_path);
- while( tmppath[0]!='\0' )
- {
- while( tmppath[0]==';' ) tmppath++;
- start = tmppath;
- while( tmppath[0]!='\0' && tmppath[0]!=';' ) tmppath++;
- tmppath[0] = '\0'; tmppath++;
- sprintf(newname,"%s%c%s.cmm",start,strchr(start,'/')?'/':'\\',path.name);
- if( fp = fopen(newname,"r") )
- {
- fclose(fp);
- return FullPath(newname);
- }
- }
-
- // Else not found
- return NULL;
- }
-
- /* ---------------------------------------------------------------------- */
-
- next_token(line,index)
- {
- command = ""; j = 0;
- while( isspace(line[index]) ) index++;
- while( line[index] && !isspace(line[index]) )
- command[j++] = line[index++];
- while( isspace(line[index]) ) index++;
- command[j] = '\0';
- return command;
- }
-
- /* ---------------------------------------------------------------------- */
-
- // All these functions return the name of the label we have to GOTO, or ""
- // if none.
-
-
- /*
- * We just ignore the line.
- */
- REM_handler(the_line,ptr,line_num)
- {
- return "";
- }
-
-
-
- /*
- * We dump the text to the terminal. The exceptions are if we have 'echo on'
- * or 'echo off'.
- */
- ECHO_handler(the_line,ptr,line_num)
- {
- if( !stricmp(the_line+ptr,"ON") )
- {
- echo = 1;
- return "";
- }
- if( !stricmp(the_line+ptr,"OFF") )
- {
- echo = 0;
- return "";
- }
-
- printf("%s\n",the_line+ptr);
- return "";
- }
-
-
-
- /*
- * If no parameter, print the current directory. Otherwise, set the current
- * directory to what is given.
- */
- CD_handler(the_line,ptr,line_num)
- {
- if( the_line[ptr]=='\0' )
- {
- printf("%s\n",getcwd(buffer));
- return "";
- }
- if( my_chdir(the_line+ptr) )
- printf("The system cannot find the path specified at line %d.\n",line_num);
- return "";
- }
-
-
- /*
- * Simply clear the screen.
- */
- CLS_handler(the_line,ptr,line_num)
- {
- ScreenClear();
- return "";
- }
-
-
- /*
- * TYPE a file to the terminal. This is an incredibly simple routine. Use
- * MORE for some options.
- */
- TYPE_handler(the_line,ptr,line_num)
- {
- if( fp = fopen(the_line+ptr,"r") )
- {
- while( 1 )
- {
- if( (newline = fgets(fp))==NULL ) break;
- printf("%s",newline);
- }
- fclose(fp);
- } else {
- printf("Unable to open file \"%s\" at line %d.\n",the_line+ptr,line_num);
- }
- return "";
- }
-
-
-
- /*
- * Since the variable we need to change is a local to one of our callers,
- * we pass back a command to it to tell it to do what we want.
- */
- SHIFT_handler(the_line,ptr,line_num)
- {
- return special_command;
- }
-
-
-
- /*
- * Just waits for the user to press any key.
- */
- PAUSE_handler(the_line,ptr,line_num)
- {
- printf("Press any key when ready . . . "); fflush(stdout);
- getch();
- printf("\n");
- return "";
- }
-
-
-
- /*
- * Invoke a new batch file and return to this one when it finishes
- */
- CALL_handler(the_line,ptr,line_num)
- {
- // Set up a new argc/argv array and call main again.
- strcpy(newargv[0],"CEnvi");
- newargc = 1;
- while( the_line[ptr]!='\0' )
- {
- command = next_token(the_line,ptr);
- strcpy(newargv[newargc++],command);
- while( isspace(the_line[ptr]) ) ptr++;
- }
- main(newargc,newargv);
- return "";
- }
-
-
-
- /*
- * The _EVIL_ goto command...
- */
- GOTO_handler(the_line,ptr,line_num)
- {
- return the_line+ptr;
- }
-
-
-
- /*
- * No, this does not simulate a person skilled in dealing with evil
- * Egyptian gods...
- */
- SET_handler(the_line,ptr,line_num)
- {
- if( defined(_NWNLM_) )
- {
- printf("Netware has no environment variables at line %d.\n",line_num);
- return "";
- }
-
- if( the_line[ptr]=='\0' )
- {
- array = getenv();
- for( ii=0;ii<GetArraySpan(array);ii++ )
- {
- printf("%s=%s\n",array[ii],getenv(array[ii]));
- }
- return "";
- }
-
- // Else we extract the name and see if we have a '=' or not.
- command = next_token(the_line,ptr);
-
- if( (where = strchr(command,'='))!=NULL )
- {
- where[0] = '\0';
- strcpy(env_var,command);
- strcpy(new_val,where+1);
- } else {
- strcpy(env_var,command);
- new_val = NULL;
- if( the_line[ptr]=='=' )
- {
- while( isspace(the_line[++ptr]) );
- strcpy(new_val,the_line+ptr);
- }
- }
-
- if( new_val==NULL )
- {
- printval = getenv(env_var);
- printf("%s=%s\n",env_var,(printval!=NULL)?printval:"");
- } else {
- putenv(env_var,new_val);
- }
- return "";
- }
-
-
-
- /*
- * A simple looping construct.
- */
- FOR_handler(the_line,ptr,line_num)
- {
- command = next_token(the_line,ptr);
- if( command[0]!='%' )
- {
- printf("Illegal loop variable in FOR statement at line %d.\n",line_num);
- return "";
- }
- strcpy(loop_variable,command);
- command = next_token(the_line,ptr);
-
- if( stricmp(command,"IN") )
- {
- printf("Malformed FOR statement, missing IN clause at line %d.\n",line_num);
- return "";
- }
- if( the_line[ptr++]!='(' )
- {
- printf("Malformed FOR statement, missing open parenthesis at line %d.\n",line_num);
- }
-
- // Next we need to collect all the things we index over...
-
- undefine(list); list_index = 0;
- done = 0;
- while( !done )
- {
- command = next_token(the_line,ptr);
- if( command[strlen(command)-1]==')' )
- {
- command[strlen(command)-1] = '\0'; done = 1;
- }
- if( command[0]!='\0' )
- {
- if( strcspn(command,"*?")==strlen(command) )
- {
- strcpy(list[list_index++],command);
- } else {
- files = Directory(command);
- for( i=0;files && i<=GetArraySpan(files);i++ )
- strcpy(list[list_index++],files[i].name);
- }
- }
- }
-
- command = next_token(the_line,ptr);
- if( stricmp(command,"DO") )
- {
- printf("Malformed FOR statement after arg list at line %d.\n",line_num);
- return "";
- }
- for( i=0;i<list_index;i++ )
- {
- strcpy(to_do,the_line+ptr);
- while( (indx = strstr(to_do,loop_variable))!=NULL )
- {
- index = indx-to_do;
- strcpy(new_do,to_do);
- strcpy(new_do+index,list[i]);
- strcat(new_do,to_do+index+strlen(loop_variable));
- strcpy(to_do,new_do);
- }
- process_command(to_do,line_num);
- }
- return "";
- }
-
-
-
- /*
- * And the testing construct.
- */
- IF_handler(the_line,ptr,line_num)
- {
- command = next_token(the_line,ptr);
-
- notted = 0;
-
- if( !stricmp(command,"NOT") )
- {
- notted = 1;
- command = next_token(the_line,ptr);
- }
-
- // Here we decide which of the three considitions we have.
- if( !stricmp(command,"EXIST") )
- {
- command = next_token(the_line,ptr);
-
- exist = (fp = fopen(command,"r"))!=NULL;
- if( fp ) fclose(fp);
- if( notted^exist )
- {
- return process_command(=the_line+ptr,line_num);
- }
- return "";
- }
-
- if( !stricmp(command,"ERRORLEVEL") )
- {
- command = next_token(the_line,ptr,line_num);
-
- testlevel = atoi(command);
-
- command = next_token(the_line,ptr);
-
- if( notted^(errorlevel>=testlevel) )
- {
- return process_command(=the_line+ptr,line_num);
- }
- return "";
- }
-
- if( where = strstr(command,"==") )
- {
- where[0] = 0; where += 2;
- if( notted^!stricmp(command,where) )
- {
- return process_command(=the_line+ptr,line_num);
- }
- return "";
- }
-
-
- printf("Unrecognized IF syntax beginning with %s at line %d.\n",command,line_num);
- return "";
- }
-
-
- command_names = {
- "REM", "ECHO", "CD", "CLS", "TYPE", "SHIFT", "CAUSE", "CALL", "SET",
- "GOTO", "FOR", "IF", "PAUSE"
- };
-
- /* ---------------------------------------------------------------------- */
-
- process_command(the_line,line_num)
- {
- ptr = 0; while( isspace(the_line[ptr]) ) ptr++;
-
- // If the line is blank, we skip it
-
- if( the_line[ptr]=='\n' || the_line[ptr]=='\0' ) return "";
-
- // If it is a ':LABEL' line, we skip it.
-
- if( the_line[ptr]==':' ) return "";
-
-
- // Else it is either an internal command, a .CMM script, or we dump it
- // to the system processor.
-
- mark = ptr;
- command = next_token(the_line,ptr);
-
- // ----------------------------------------------------------------------
- // Here we process all internal commands
- // ----------------------------------------------------------------------
-
- for( i=0;i<=GetArraySpan(command_names);i++ )
- {
- if( !stricmp(command_names[i],command) )
- {
- sprintf(func_name,"%s_handler",command_names[i]);
- return function(func_name,the_line,ptr,line_num);
- }
- }
-
- // ----------------------------------------------------------------------
- // We check to see if it is a drive designation
- // ----------------------------------------------------------------------
-
- if( command[1]==':' && strlen(command)==2 )
- {
- #define ORD_DOS32SETDEFAULTDISK 220
- if( defined(_OS2_) )
- {
- DynamicLink("doscalls",ORD_DOS32SETDEFAULTDISK,BIT32,CDECL,
- toupper(command[0])-'A'+1);
- }
- if( defined(_NTWIN_) || defined(_NTCON_) )
- {
- CD_handler(command,0,line_num);
- }
- if( defined(_WINDOWS_) || defined(_DOS_) || defined(_DOS32_) )
- {
- lReg.ah = 0x0E;
- lReg.dl = toupper(command[0]) - 'A';
- interrupt(0x21,lReg);
- }
- return "";
- }
-
- // -----------------------------------------------------------------------
- // Otherwise, it is either a CMM script or we dump it to the command shell
- // Here we check to see if we can find a .CMM file to run.
- // -----------------------------------------------------------------------
-
- if( (filename = find_cmm(command)) )
- {
- strcat(filename," ");
- strcat(filename,the_line+ptr);
- errorlevel = Interpret(filename,
- INTERP_FILE |
- INTERP_NOINHERIT_LOCAL |
- INTERP_NOINHERIT_GLOBAL );
- return "";
- }
-
- errorlevel = system(the_line+mark);
-
- return "";
- }
-
- /* ---------------------------------------------------------------------- */
-
- /*
- * Ok, we have a list of internal commands. All other commands are
- * either CMM scripts which we interpret, else they are system commands
- * which we execute as appropriate for each system.
- *
- * Lines beginning with a ':' are ignored except when searching for
- * GOTO targets.
- */
-
- main(argc,argv)
- {
- setup();
- plus = 1; // the offset into the parameter array for substitution
-
-
- if( argc<2 || !strcmp(argv[1],"/?") )
- {
- usage();
- }
-
- if( (fp = fopen(argv[1],"r"))==NULL )
- {
- path = SplitFileName(argv[1]);
- sprintf(newname,"%s%s.bat",path.dir,path.name);
- fp = fopen(newname,"r");
- }
- if( fp==NULL )
- {
- printf("Could not open source file \"%s\" for reading.\n",argv[1]);
- return 1;
- }
-
- line_count = 0;
- while( 1 )
- {
- if( (newline = fgets(fp))==NULL ) break;
- strcpy( lines[line_count++],newline);
- }
- fclose(fp);
-
- // All right. We have the file in memory as a sequence of lines. Start doing them.
-
- for( i = 0;i<line_count;i++ )
- {
- strcpy(the_line,lines[i]);
-
- // First we do any parameter substitution in the line
- the_line = substitute_line(the_line,argc-plus,argv+plus);
-
- while( isspace(the_line[0]) ) the_line++;
- if( the_line[0]=='@' )
- {
- echo_it = 0; the_line++;
- } else {
- echo_it = echo;
- }
-
- if( echo_it ) printf("\n%s>%s\n",FullPath("."),the_line);
-
- redir_stdout = NULL;
- redir_stdin = NULL;
- redir_new = NULL;
- to_delete = NULL;
- mode = "";
- in_quotes = 0;
- start_from = 0;
-
- while( the_line[0] )
- {
- next_line = "";
-
- while( (loc = strcspn(the_line+start_from,"\"|<>"))
- !=strlen(the_line+start_from) )
- {
- loc += start_from;
- if( the_line[loc]=='\"' )
- {
- in_quotes = 1 - in_quotes;
- start_from = loc+1;
- continue;
- }
-
- if( in_quotes )
- {
- start_from = loc+1;
- continue;
- }
-
- if( the_line[loc]=='<' )
- {
- if( redir_stdin )
- {
- fprintf(stderr,"Input already redirected.\n");
- exit(EXIT_FAILURE);
- }
-
- newloc = loc+1;
- while( isspace(the_line[newloc]) ) newloc++;
- locstart = newloc;
- while( the_line[newloc] && !isspace(the_line[newloc]) )
- newloc++;
- tmp = the_line[newloc]; the_line[newloc] = 0;
- strcpy(redir_stdin,the_line+locstart);
- the_line[newloc] = tmp;
- strcpy(the_line+loc,the_line+newloc);
- continue;
- }
- if( the_line[loc]=='>' )
- {
- if( redir_stdout )
- {
- fprintf(stderr,"Output already redirected.\n");
- exit(EXIT_FAILURE);
- }
-
- mode = "wt";
- newloc = loc+1;
- if( the_line[newloc]=='>' )
- {
- mode = "at";
- newloc++;
- }
-
- while( isspace(the_line[newloc]) ) newloc++;
- locstart = newloc;
- while( the_line[newloc] && !isspace(the_line[newloc]) )
- newloc++;
- tmp = the_line[newloc]; the_line[newloc] = 0;
- strcpy(redir_stdout,the_line+locstart);
- the_line[newloc] = tmp;
- strcpy(the_line+loc,the_line+newloc);
- continue;
- }
-
- if( the_line[loc]=='|' )
- {
- if( redir_stdout )
- {
- fprintf(stderr,"Output is already redirected to a file.\n");
- exit(EXIT_FAILURE);
- }
- mode = "wt";
- strcpy(next_line,the_line+loc+1);
- the_line[loc] = 0;
- strcpy(redir_new,tmpnam());
- strcpy(redir_stdout,redir_new);
- break;
- }
- }
-
- if( redir_stdout && !freopen(redir_stdout,mode,stdout) )
- {
- fprintf(stderr,"Unable to open output redirection file \"%s\".\n",
- redir_stdout);
- exit(EXIT_FAILURE);
- }
-
- if( redir_stdin && !freopen(redir_stdin,"r",stdin) )
- {
- fprintf(stderr,"Unable to open input redirection file \"%s\".\n",
- redir_stdin);
- exit(EXIT_FAILURE);
- }
-
- label = process_command(the_line,i+1);
- if( to_delete ) remove(to_delete);
- to_delete = NULL;
- if( redir_stdout ) { fclose(stdout); redir_stdout = NULL; }
- if( redir_stdin ) { fclose(stdin); }
- redir_stdin = redir_new; to_delete = redir_new; redir_new = NULL;
-
- strcpy(the_line,next_line);
- }
-
- if( !stricmp(label,special_command) )
- {
- plus++; continue;
- }
-
- if( label[0]!='\0' )
- {
- yep = 0;
- length = strlen(label);
- for( j=0;!yep && j<line_count;j++ )
- {
- if( lines[j][0]==':' && !strncmp(lines[j]+1,label,length) )
- {
- yep = 1;
- i = j - 1;
- }
- }
- if( !yep )
- {
- printf("Label \"%s\" not found.\n",label);
- return 1;
- }
- }
- }
- }
-